<template>
  <PageWrapper>
    <!-- 笔记 -->
    <CollapseContainer class="mt-5" title="文档">
      <markdown-viewer :value="getDoc()" />
    </CollapseContainer>

    <CollapseContainer class="mt-5" title="watch-ref">
      <ol>
        <li>基本类型:{{ title }}<Button @click="changeTitle">修改</Button></li>
        <li>
          对象类型:{{ person }}
          <Button @click="changePersonName">修改 person.name</Button>
          <Button @click="changePersonCity">修改 person.address.city</Button>
          <Button @click="changePerson">修改整个 person</Button>
        </li>
      </ol>
      <template #action>
        <Icon icon="ant-design:code-outlined" class="mr-1" :size="26" @click="openSource('深度引用', getSource())" />
      </template>
    </CollapseContainer>

    <!-- 源码组件 -->
    <SourceDrawer ref="sourceDrawer" />
  </PageWrapper>
</template>
<script lang="ts" setup>
  import { CollapseContainer } from '@/components/Container';
  import { MarkdownViewer } from '@/components/Markdown';
  import { PageWrapper } from '@/components/Page';
  import { Button } from '@/components/Button';
  import SourceDrawer from '@/learn/SourceDrawer.vue';
  import { Icon } from '@/components/Icon';
  // 需要引入 computed 方法
  import { ref, watch } from 'vue';
  import { useMessage } from '@/hooks/web/useMessage';

  const { createMessage } = useMessage();

  // 定义子组件引用
  let sourceDrawer = ref<any>(null);
  function openSource(title: string, content: string) {
    sourceDrawer.value.open({ title, content, width: '60%' });
  }

  let title = ref<string>('watch-ref 示例');
  let person = ref({ id: 1001, name: 'lisi', address: { province: '河南', city: '郑州' } });
  function changeTitle() {
    title.value += '~';
  }

  function changePersonName() {
    person.value.name += '~';
  }
  function changePersonCity() {
    person.value.address.city += '*-';
  }
  function changePerson() {
    person.value = { id: 2001, name: 'zhangsan', address: { province: '河北', city: '石家庄' } };
  }

  watch(title, (newVal, oldVal) => {
    createMessage.info('title 值发生了变化, 原:' + oldVal + ', 新:' + newVal);
  });
  watch(person, (newVal, oldVal) => {
    // 只有对象地址发生变更时，才会触发
    // watch 监视的为对象时，oldVal 无意义，因为 oldVal 和 newVal 指向的对象地址一样，因此值是一样的
    console.log('原值:', oldVal, ', 新值:', newVal);
    createMessage.error('对象地址监视: person 对象地址发生了变化, 原:' + oldVal + ', 新:' + newVal);
  });
  watch(
    person,
    (newVal, oldVal) => {
      // 对象地址或对象内部属性发生变更，都会触发
      createMessage.info('深度监视: person 属性发生了变化，或person地址发生了变化, 原:' + oldVal + ', 新:' + newVal);
    },
    { deep: true, immediate: true },
  );
</script>

<script lang="ts">
  function getDoc() {
    return `
### 监视 ref 响应式对象
* 监视基本类型的对象: 回调方法中，oldVal 表示原来的值
* 监视对象类型:
  * 默认只能监听对象地址发生变化，及对象被做了整体替换
  * 可以通过设置 deep:true 参数，设置同时监听内部属性
  * 监听回调方法中的 oldVal 参数没有意义，因为指向的地址相同，所以 oldVal 和 newVal 相同
* 立即执行: 默认初次赋值时不会触发回调，可以通过设置 immediate 为true，实现在初始化的时候回调
`;
  }

  function getSource() {
    return `
\`\`\`html
<template>
  <CollapseContainer class="mt-5" title="watch-ref">
    <ol>
      <li>基本类型:{{ title }}<Button @click="changeTitle">修改</Button></li>
      <li>
        对象类型:{{ person }}
        <Button @click="changePersonName">修改 person.name</Button>
        <Button @click="changePersonCity">修改 person.address.city</Button>
        <Button @click="changePerson">修改整个 person</Button>
      </li>
    </ol>
    <template #action>
      <Icon icon="ant-design:code-outlined" class="mr-1" :size="26" @click="openSource('深度引用', getSource())" />
    </template>
  </CollapseContainer>
</template>

\<script lang="ts" setup\>
import { CollapseContainer } from '@/components/Container';
  import { MarkdownViewer } from '@/components/Markdown';
  import { PageWrapper } from '@/components/Page';
  import { Button } from '@/components/Button';
  import SourceDrawer from '@/learn/SourceDrawer.vue';
  import { Icon } from '@/components/Icon';
  // 需要引入 computed 方法
  import { ref, watch } from 'vue';
  import { useMessage } from '@/hooks/web/useMessage';

  const { createMessage } = useMessage();

  // 定义子组件引用
  let sourceDrawer = ref<any>(null);
  function openSource(title: string, content: string) {
    sourceDrawer.value.open({ title, content, width: '60%' });
  }

  let title = ref<string>('watch-ref 示例');
  let person = ref({ id: 1001, name: 'lisi', address: { province: '河南', city: '郑州' } });
  function changeTitle() {
    title.value += '~';
  }

  function changePersonName() {
    person.value.name += '~';
  }
  function changePersonCity() {
    person.value.address.city += '*-';
  }
  function changePerson() {
    person.value = { id: 2001, name: 'zhangsan', address: { province: '河北', city: '石家庄' } };
  }

  watch(title, (newVal, oldVal) => {
    createMessage.info('title 值发生了变化, 原:' + oldVal + ', 新:' + newVal);
  });
  watch(person, (newVal, oldVal) => {
    // 只有对象地址发生变更时，才会触发
    // watch 监视的为对象时，oldVal 无意义，因为 oldVal 和 newVal 指向的对象地址一样，因此值是一样的
    console.log('原值:', oldVal, ', 新值:', newVal);
    createMessage.error('对象地址监视: person 对象地址发生了变化, 原:' + oldVal + ', 新:' + newVal);
  });
  watch(
    person,
    (newVal, oldVal) => {
      // 对象地址或对象内部属性发生变更，都会触发
      createMessage.info('深度监视: person 属性发生了变化，或person地址发生了变化, 原:' + oldVal + ', 新:' + newVal);
    },
    { deep: true, immediate: true },
  );
\</script\>
\`\`\`
`;
  }
</script>

<style lang="less" scoped>
  button {
    margin-left: 5px;
  }
</style>
